<?php

namespace App\Http\Controllers\V1;

use App\Http\Controllers\ApiBaseController;
use App\Models\BalanceLog;
use App\Models\ChannelOrder;
use App\Models\CzOrder;
use App\Models\CzOrderLog;
use App\Models\SysDictData;
use App\Models\SysUser;
use App\Services\CzOrderService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use EasyWeChat\Factory;

class CzOrderController extends ApiBaseController
{
    protected $baseUrl;
    protected $appid;
    protected $mch_id;
    protected $secret;
    protected $miniApp;
    protected $payApp;
    protected $paykey;

    public function __construct(Request $request)
    {
        $this->baseUrl = env('APP_URL');
        $this->appid = env('min_appid');
        $this->secret = env('min_secret');
        $mch_id = env('mch_id');
        $this->paykey = env('key');
        $notify_url = env('notify_url');
        parent::__construct($request);

        $this->miniApp = Factory::miniProgram([
            'log' => [
                'level' => 'debug',
                'file' => storage_path('wechat.log'),
            ],
            "response_type" => "array",
            "app_id" => $this->appid,
            "secret" => $this->secret,
        ]);

        // $config = [
        //     'app_id' => $this->appid, //appid为小程序aphid
        //     'mch_id' => $mch_id,
        //     'key' => $this->paykey,
        //     'cert_path' => base_path(env("cert_path")),
        //     'key_path' =>  base_path(env("key_path")),
        //     'notify_url' => $notify_url
        // ];
        // $this->payApp = Factory::payment($config);
    }
    public function userOrderList(Request $request)
    {
        $params  = $request->all();
        if ((!$params['updated_at']['beginTime'] || !$params['updated_at']['endTime']) && (!$params['params']['beginTime'] || !$params['params']['endTime'])) {
            return error('请选择时间范围');
        }

        $sort_column = "id";
        if (isset($params['order'])) {
            $sort_column = "updated_at";
        }
        $params['order'] = $params['order'] ?? "desc";
        $params['pay_status'] =  1;
        // if (isset($params['order'])) {
        //     $params['order'] = $params['order'];
        // }
        $paginator = CzOrder::filter($params)->dataFilter()->with([
            'user' => function ($query) {
                $query->select('id', 'username');
            },
            'pay' => function ($query) {
                $query->select('id', 'payment_name');
            },
            'channel' => function ($query) {
                $query->select('id', 'channel_name');
            }
        ])->orderBy($sort_column, $params['order'])->paginate($this->pageSize);

        $newList = $paginator->items();
        foreach ($newList as $key => &$val) {
            // if ($key == "pay_type") {
            //     if ($val == "jinfu") {
            //         $val = $val . "-对私";
            //     }
            //     if ($val == "jinfu2") {
            //         $val = $val . "-对公";
            //     }
            // }
            if ($val['pay_type'] == "jinfu") {
                $val['pay_type'] = $val['pay_type'] . "-对私";
            }
            if ($val['pay_type'] == "jinfu2") {
                $val['pay_type'] = $val['pay_type'] . "-对公";
            }
        }
        $result = [
            'rows' => $newList,
            'total' => $paginator->total(), // 获取结果集中的数据总数
            'last_page' => $paginator->lastPage(),
            'currentPage' => $paginator->currentPage()
        ];
        return success($result);
    }

    public function statics(Request $request)
    {
        $params = $request->only(['user_id', 'product_id', 'biz_type', 'isp', 'province_id', 'city_id', 'face_value', 'params', 'channel_id', 'updated_at']);
        $params['pay_status'] = 1;


        $total_info = CzOrder::filter($params)->selectRaw('COUNT(*) AS counts,SUM(price) AS sum_money,SUM(cost) AS sum_cost')->first();
        $total_nums = $total_info->counts ?? 0;
        $total_money = $total_info->sum_money ?? 0;
        $total_cost = $total_info->sum_cost ?? 0;

        $success_info = CzOrder::filter($params)->where('order_status', 3)->selectRaw('COUNT(*) AS counts,SUM(price) AS sum_money,SUM(cost) AS sum_cost')->first();
        $success_nums = $success_info->counts ?? 0;
        $success_money = $success_info->sum_money ?? 0;
        $success_cost = $success_info->sum_cost ?? 0;

        $create_order = CzOrder::filter($params)->whereIn('order_status', [1])->sum('price');
        $ing_order = CzOrder::filter($params)->whereIn('order_status', [2])->sum('price');
        $cache_order = CzOrder::filter($params)->whereIn('order_status', [5])->sum('price');
        $fail_ing_order = CzOrder::filter($params)->whereIn('order_status', [6])->sum('price');


        $fail_info = CzOrder::filter($params)->where('order_status', 4)->selectRaw('COUNT(*) AS counts,SUM(price) AS sum_money,SUM(cost) AS sum_cost')->first();
        $fail_nums = $fail_info->counts ?? 0;
        $fail_money = $fail_info->sum_money ?? 0;
        $fail_cost = $fail_info->sum_cost ?? 0;


        // 退款金额
        if (isset($params['params']['beginTime'])) {
            // 默认当前年初
            $start = date("Y", strtotime($params['params']['beginTime'])) . "-01-01 00:00:00";
            if (isset($params['user_id'])) {
                $refund_money = CzOrder::where('create_by', $params['user_id'])->where('pay_status', 1)->where('order_status', 4)
                    ->whereBetween('created_at', [strtotime($start), strtotime($params['params']['beginTime'])])
                    ->whereBetween('updated_at', [strtotime($params['params']['beginTime']), strtotime($params['params']['endTime'])])->sum('price'); //总售价
            } else {
                $refund_money = CzOrder::where('order_status', 4)
                    ->where('pay_status', 1)
                    ->whereBetween('created_at', [strtotime($start), strtotime($params['params']['beginTime'])])
                    ->whereBetween('updated_at', [strtotime($params['params']['beginTime']), strtotime($params['params']['endTime'])])->sum('price'); //总售价
            }
        }
        // 累计加款
        $add_money = BalanceLog::filter($params)->where('type', 1)->sum("money");
        // 扣款
        $del_money = BalanceLog::filter($params)->where('type', 2)->sum("money");


        // 期初期末
        $start_money = 0;
        $end_money = 0;
        if (isset($params['user_id'])) {
            $merchant = SysUser::find($params['user_id']);
            if (isset($params['params']['beginTime'])) {
                $start_info = BalanceLog::filter($params)->first();
                if ($start_info) {
                    $start_money = $start_info->bf_balance;
                }

                $end_info = BalanceLog::filter($params)->orderBy('created_at', 'desc')->first();
                // var_dump($end_info->toArray());
                if ($end_info) {
                    // af_money
                    $end_money = $end_info->af_balance;
                }

                if (!$end_info || !$start_info) {
                    $start_money = $merchant->balance;
                    $end_money = $merchant->balance;
                }
            }
        }


        $processing_nums = $total_nums - $success_nums - $fail_nums;
        $processing_money = number_format(($total_money - $success_money - $fail_money), 2);

        $profit = number_format(($success_money - $success_cost), 2);
        $data = [
            'total_nums' => $total_nums,
            'total_money' => $total_money,
            'total_cost' => $total_cost,

            'success_nums' => $success_nums,
            'success_money' => $success_money,
            'success_cost' => $success_cost,

            "refund_money" => $refund_money ?? "",

            "add_money" => $add_money ?? 0,
            "del_money" => $del_money ?? 0,

            "start_money" => $start_money ?? 0,
            "end_money" => $end_money ?? 0,

            'processing_nums' => $processing_nums,
            'processing_money' => $processing_money ?? 0,

            'fail_nums' => $fail_nums,
            'fail_money' => $fail_money,
            'fail_cost' => $fail_cost,

            'profit' => $profit ?? 0,


            "create_order" => $create_order,
            "ing_order" => $ing_order,
            "fail_ing_order" => $fail_ing_order,
            "cache_order" => $cache_order,
        ];
        return success(['data' => $data]);
    }
    public function getOrderStatus($type)
    {
        $dictData = SysDictData::where('dict_type', 'cz_order_status')->get();
        $dictData = $dictData->toArray();
        $res = '';
        foreach ($dictData as $key => $value) {
            if ($value['dict_value'] == $type) {
                $res = $value['dict_label'];
                break;
            }
        }
        return $res;
    }
    public function exportUserOrder(Request $request)
    {
        // var_dump($request['ids']);
        // return;

        set_time_limit(600);
        $params  = $request->all();
        if (!isset($params['ids'])) {
            // if (!$params['params']['beginTime'] || !$params['params']['endTime']) {
            //     return error('参数错误');
            // }
            if ((!$params['updated_at']['beginTime'] || !$params['updated_at']['endTime']) && (!$params['params']['beginTime'] || !$params['params']['endTime'])) {
                return error('请选择时间范围');
            }
        }

        $sort_column = "id";
        if (isset($params['order'])) {
            $sort_column = "updated_at";
        }
        $params['order'] = $params['order'] ?? "desc";
        $fileName = "客户充值订单导出[" . date('YmdHi') . "].csv";
        // 清空输出流，防止有别的信息
        ob_end_clean();
        // 打开一个输出流
        ob_start();
        // 设置header信息
        header("Content-Type: text/csv");
        header("Content-Disposition:filename=" . $fileName);
        header("Access-Control-Allow-Origin: *");

        // 打开文件流
        $fileHandle = fopen('php://output', 'w');
        //转码 防止乱码
        fwrite($fileHandle, chr(0xEF) . chr(0xBB) . chr(0xBF));
        $header_data = [
            '订单号', '客户订单号', '批量订单号', '产品', '手机号', '面值', '成本', '价格', '订单状态', '渠道', '创建时间', '修改时间', '客户', '归属地'
        ];
        if (!empty($header_data)) {
            fputcsv($fileHandle, $header_data);
        }
        // 先把标题写进去
        //        fputcsv($fileHandle, $title);
        if (isset($request['ids'])) {
            // 导出部分
            CzOrder::whereIn('id', $request['ids'])->dataFilter()->with([
                'user' => function ($query) {
                    $query->select('id', 'username');
                },
                'channel' => function ($query) {
                    $query->select('id', 'channel_name');
                }
            ])->where('pay_status', 1)->orderBy($sort_column, $params['order'])
                ->chunk(10000, function ($items) use ($fileHandle) {
                    $arrs = $items->toArray();
                    foreach ($arrs as $item) {
                        $tmp_data = [
                            $item['order_sn'],
                            $item['user_order_sn'],
                            $item['batch_order_sn'],
                            $item['product_name'],
                            $item['mobile'],
                            $item['face_value'],
                            $item['cost'],
                            $item['price'],
                            $this->getOrderStatus($item['order_status']),
                            $item['channel'] ? $item['channel']['channel_name'] : '无',
                            $item['created_at'],
                            $item['updated_at'],
                            $item['user'] ? $item['user']['username'] : '无',
                            $item['area_name']

                        ];
                        fputcsv($fileHandle, $tmp_data);
                    }
                    //每2000条释放一次资源
                    ob_flush();
                    flush();
                });
        } else {
            CzOrder::filter($params)->dataFilter()->with([
                'user' => function ($query) {
                    $query->select('id', 'username');
                },
                'channel' => function ($query) {
                    $query->select('id', 'channel_name');
                }
            ])->where('pay_status', 1)->orderBy($sort_column, $params['order'])
                ->chunk(10000, function ($items) use ($fileHandle) {
                    $arrs = $items->toArray();
                    foreach ($arrs as $item) {
                        $tmp_data = [
                            $item['order_sn'],
                            $item['user_order_sn'],
                            $item['batch_order_sn'],
                            $item['product_name'],
                            $item['mobile'],
                            $item['face_value'],
                            $item['cost'],
                            $item['price'],
                            $this->getOrderStatus($item['order_status']),
                            $item['channel'] ? $item['channel']['channel_name'] : '无',
                            $item['created_at'],
                            $item['updated_at'],
                            $item['user'] ? $item['user']['username'] : '无',
                            $item['area_name']

                        ];
                        fputcsv($fileHandle, $tmp_data);
                    }
                    //每2000条释放一次资源
                    ob_flush();
                    flush();
                });
        }
        //释放资源
        ob_flush();
        flush();
        ob_end_clean();
    }

    public function exportChannelOrder(Request $request)
    {
        $params  = $request->all();
        if (!isset($params['ids'])) {
            // if (!$params['params']['beginTime'] || !$params['params']['endTime']) {
            //     return error('请选择时间范围');
            // }
            if ((!$params['updated_at']['beginTime'] || !$params['updated_at']['endTime']) && (!$params['params']['beginTime'] || !$params['params']['endTime'])) {
                return error('请选择时间范围');
            }
        }

        $field = "order_sn, product_name, face_value, mobile, cost, price, created_at";
        $fileName = "渠道充值订单导出[" . date('YmdHi') . "].csv";

        $sort_column = "id";
        if (isset($params['order'])) {
            $sort_column = "updated_at";
        }
        $params['order'] = $params['order'] ?? "desc";
        // 清空输出流，防止有别的信息
        ob_end_clean();
        // 打开一个输出流
        ob_start();
        // 设置header信息
        header("Content-Type: text/csv");
        header("Content-Disposition:filename=" . $fileName);
        header("Access-Control-Allow-Origin: *");

        // 打开文件流
        $fileHandle = fopen('php://output', 'w');
        //转码 防止乱码
        fwrite($fileHandle, chr(0xEF) . chr(0xBB) . chr(0xBF));
        $header_data = [
            '平台订单号', '推送订单号', '渠道订单号', '产品', '面值', '手机号', '状态', '渠道价格', '创建时间', '更新时间'
        ];
        if (!empty($header_data)) {
            fputcsv($fileHandle, $header_data);
        }
        $status_map = [
            1 => '初始化',
            2 => '充值中',
            3 => '充值完成',
            4 => '充值失败'
        ];
        // 先把标题写进去
        //        fputcsv($fileHandle, $title);
        if (isset($request['ids'])) {
            ChannelOrder::whereIn('id', $request['ids'])->dataFilter()->with([
                'order' => function ($query) {
                    $query->where('pay_status', 1)->select('id', 'product_name', 'mobile', 'face_value', 'price', 'area_name', 'province_id', 'city_id', 'order_status', 'isp', 'biz_type', 'hf_type');
                }
            ])->orderBy($sort_column, $params['order'])->chunk(10000, function ($items) use ($fileHandle, $status_map) {
                $arrs = $items->toArray();
                foreach ($arrs as $item) {
                    $w_data = [
                        $item['order_sn'],
                        $item['push_order_sn'],
                        $item['channel_order_sn'],
                        $item['order']['product_name'],
                        $item['order']['face_value'],
                        $item['order']['mobile'],
                        $status_map[$item['channel_order_status']],
                        $item['channel_price'],
                        $item['created_at'],
                        $item['updated_at'],
                    ];
                    fputcsv($fileHandle, $w_data);
                }
                //每2000条释放一次资源
                ob_flush();
                flush();
            });
        } else {
            ChannelOrder::filter($params)->dataFilter()->with([
                'order' => function ($query) {
                    $query->where('pay_status', 1)->select('id', 'product_name', 'mobile', 'face_value', 'price', 'area_name', 'province_id', 'city_id', 'order_status', 'isp', 'biz_type', 'hf_type');
                }
            ])->orderBy($sort_column, $params['order'])->chunk(10000, function ($items) use ($fileHandle, $status_map) {
                $arrs = $items->toArray();
                foreach ($arrs as $item) {
                    $w_data = [
                        $item['order_sn'],
                        $item['push_order_sn'],
                        $item['channel_order_sn'],
                        $item['order']['product_name'],
                        $item['order']['face_value'],
                        $item['order']['mobile'],
                        $status_map[$item['channel_order_status']],
                        $item['channel_price'],
                        $item['created_at'],
                        $item['updated_at'],
                    ];
                    fputcsv($fileHandle, $w_data);
                }
                //每2000条释放一次资源
                ob_flush();
                flush();
            });
        }

        //释放资源
        ob_flush();
        flush();
        ob_end_clean();
    }

    public function channelOrderList(Request $request)
    {
        $params  = $request->all();
        // if (!$params['params']['beginTime'] || !$params['params']['endTime']) {
        //     return error('请选择时间范围');
        // }
        if ((!$params['updated_at']['beginTime'] || !$params['updated_at']['endTime']) && (!$params['params']['beginTime'] || !$params['params']['endTime'])) {
            return error('请选择时间范围');
        }

        $sort_column = "id";
        if (isset($params['order'])) {
            $sort_column = "updated_at";
        }
        $params['order'] = $params['order'] ?? "desc";
        $paginator = ChannelOrder::filter($params)->dataFilter()->with([
            'user' => function ($query) {
                $query->select('id', 'username');
            },
            'channel' => function ($query) {
                $query->select('id', 'channel_name');
            },
            'order' => function ($query) {
                $query->where('pay_status', 1)->select('id', 'product_name', 'mobile', 'face_value', 'price', 'area_name', 'province_id', 'city_id', 'order_status', 'isp', 'biz_type', 'hf_type');
            }
        ])->orderBy($sort_column, $params['order'])->paginate($this->pageSize);
        return success(page_format($paginator));
    }
    /*终止订单*/
    public function stopCzOrder(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $order_list = $model
            ->where('order_status', 2)
            ->whereIn('id', $id_arr)
            ->get();
        $user = auth()->user();
        foreach ($order_list as $order) {
            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]终止订单",
            ]);
            $order->is_stop = 1;
            $order->save();
        }
        return success([], '操作成功');
    }

    public function updateOrderStatus(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $is_callback = $request->post('is_callback');
        $order_status = $request->post('order_status');
        $user_pwd = $request->post('password', '');

        $user = auth()->user();
        if ($order_status == 4 && Hash::check($user_pwd, $user->password) == false) {
            return error('密码有误');
        }
        $msg = substr($request->post('remark'), 0, 100);

        $order_list = $model->with([
            'user' => function ($query) {
                $query->select('id', 'username', 'api_secret');
            }
        ])->where('pay_status', 1)->where('order_status', '<>', 4)
            ->whereIn('id', $id_arr)
            ->get();
        foreach ($order_list as $order) {
            //以失败的订单跳过
            if ($order->order_status == 4 || $order->order_status == $order_status) {
                continue;
            }

            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]手动更改订单状态[{$order->order_status}]=>[{$order_status}]",
            ]);

            //更新
            if ($msg) {
                $order->msg = substr("[手动]" . $msg, 0, 100);
            }
            $order->order_status = $order_status;
            $order->save();
            // 未支付和已退款跳过
            if ($order->refund_status == 1 || $order->pay_status == 0) {
                continue;
            }


            if ($order_status == 4) {

                if ($order->appid == 'wxaeda8fa3fb79039e') {
                    // 严选快享
                    $data = [
                        'template_id' => 'muHtejppxS9R914WjN2fCfdiyn7NRe5wgLFNOA7vCXA', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'phone_number1' => [
                                'value' => $order->mobile,
                            ],
                            'amount2' => [
                                'value' => $order->face_value,
                            ],
                            'character_string4' => [
                                'value' => $order->order_sn,
                            ],
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['kxtx']['appid'],
                        "secret" => config('mini')['kxtx']['secret'],
                    ]);
                }
                if ($order->appid == 'wxff3e969d7c6364f9') {
                    // 严选优充
                    $data = [
                        'template_id' => 'muHtejppxS9R914WjN2fCfdiyn7NRe5wgLFNOA7vCXA', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'phone_number1' => [
                                'value' => $order->mobile,
                            ],
                            'amount2' => [
                                'value' => $order->face_value,
                            ],
                            'character_string4' => [
                                'value' => $order->order_sn,
                            ],
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['kxtx']['appid'],
                        "secret" => config('mini')['kxtx']['secret'],
                    ]);
                }
                if ($order->appid == 'wxb161a3ef252af188') {
                    $data = [
                        'template_id' => 'M4vbZCuMzoSNN1Mm1OQewQ1X4sT0sl6Mt6C3HXGDZZ0', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'character_string3' => [
                                'value' => $order->order_sn,
                            ],
                            'phone_number1' => [
                                'value' => $order->mobile,
                            ],
                            'amount2' => [
                                'value' => $order->face_value,
                            ]
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['yxwy']['appid'],
                        "secret" => config('mini')['yxwy']['secret'],
                    ]);
                }
                $res = $miniApp->subscribe_message->send($data);
            }
            if ($order_status == 3) {
                if ($order->appid == 'wxaeda8fa3fb79039e') {
                    // 模版消息
                    $data = [
                        'template_id' => 'Jd0ke1RjhRJtw-on3rGHt4mukRCW3NgmyzxNmvf-pwc', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'phone_number5' => [
                                'value' => $order->mobile,
                            ],
                            'character_string4' => [
                                'value' => $order->order_sn,
                            ],
                            'amount1' => [
                                'value' => $order->face_value,
                            ],
                            'time3' => [
                                'value' => date("Y-m-d H:i:s", strtotime($order->updated_at)),
                            ],
                            // 'thing7' => [
                            //     'value' => "订单已充值成功！",
                            // ],
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['kxtx']['appid'],
                        "secret" => config('mini')['kxtx']['secret'],
                    ]);
                }
                if ($order->appid == 'wxff3e969d7c6364f9') {
                    // 严选优充
                    $data = [
                        'template_id' => 'Jd0ke1RjhRJtw-on3rGHt4mukRCW3NgmyzxNmvf-pwc', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'character_string6' => [
                                'value' => $order->order_sn,
                            ],
                            'phone_number5' => [
                                'value' => $order->mobile,
                            ],
                            'amount1' => [
                                'value' => $order->face_value,
                            ],
                            'time3' => [
                                'value' => date("Y-m-d H:i:s", strtotime($order->updated_at)),
                            ],
                            'thing7' => [
                                'value' => "订单已充值成功！",
                            ],
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['kxtx']['appid'],
                        "secret" => config('mini')['kxtx']['secret'],
                    ]);
                }
                if ($order->appid == 'wxb161a3ef252af188') {
                    $data = [
                        'template_id' => 'P5jc7JCV68Ob3hzDnIExYYRmdwGUNomaVK67L_Kpdo4', // 所需下发的订阅模板id
                        'touser' => $order->openid,     // 接收者（用户）的 openid
                        'page' => '',       // 点击模板卡片后的跳转页面，仅限本小程序内的页面。支持带参数,（示例index?foo=bar）。该字段不填则模板无跳转。
                        'data' => [         // 模板内容，格式形如 { "key1": { "value": any }, "key2": { "value": any } }
                            'character_string4' => [
                                'value' => $order->order_sn,
                            ],
                            'phone_number5' => [
                                'value' => $order->mobile,
                            ],
                            'amount1' => [
                                'value' => $order->face_value,
                            ],
                            'time3' => [
                                'value' => date('Y-m-d H:i:s', strtotime($order->updated_at)),
                            ],
                        ],
                    ];
                    $miniApp = Factory::miniProgram([
                        'log' => [
                            'level' => 'debug',
                            'file' => storage_path('wechat.log'),
                        ],
                        "response_type" => "array",
                        "app_id" => config('mini')['yxwy']['appid'],
                        "secret" => config('mini')['yxwy']['secret'],
                    ]);
                }
                $res = $miniApp->subscribe_message->send($data);
            }
            if ($order_status == 4 && $order->is_refund == 0) {
                // 异步退款
                // 微信退款 todo 一步退款
                // $czService = new CzOrderService();

                // $czService->refund($order, $msg);

                sock_queue($order->id, 'order_refund');
            }
            if ($is_callback == 1 && ($order_status == 3 || $order_status == 4) && $order->callback_url) {
                //异步回调

                // sock_queue($order->id, 'callback_user_order');
            }
        }
        return success([], '操作成功');
    }

    public function orderCallback(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');

        $order_list = $model
            ->where('pay_status', 1)
            ->whereIn('order_status', [3, 4])
            ->whereIn('id', $id_arr)
            ->get();
        foreach ($order_list as $order) {

            if ($order->callback_url) {
                //异步回调
                sock_queue($order->id, 'callback_user_order');
            }
        }
        return success([], '操作成功');
    }

    /**渠道订单更新状态*/
    public function updateChannelOrderStatus(Request $request, ChannelOrder $model)
    {
        $id_arr = $request->post('ids');
        $order_status = $request->post('order_status');
        $user_pwd = $request->post('password', '');

        $user = auth()->user();
        if ($order_status == 4 && Hash::check($user_pwd, $user->password) == false) {
            return error('密码有误');
        }
        $msg = substr($request->post('remark'), 0, 100);

        $channel_order_list = $model->whereIn('channel_order_status', [1, 2])
            ->whereIn('id', $id_arr)
            ->get();
        foreach ($channel_order_list as $channel_order) {
            //以失败的订单跳过
            if ($channel_order->channel_order_status == 4 || $channel_order->channel_order_status == $order_status) {
                continue;
            }
            CzOrderLog::create([
                'order_id' => $channel_order->order_id,
                'order_sn' => $channel_order->order_sn,
                'content' => "[{$user->username}]手动更改渠道订单[{$channel_order->push_order_sn}]状态[{$channel_order->channel_order_status}]=>[{$order_status}]",
            ]);

            //更新
            if ($msg) {
                $channel_order->msg = substr("[手动]" . $msg, 0, 100);
            }

            $channel_order->channel_order_status = $order_status;
            $channel_order->save();
            //异步操作
            sock_get(env('QUEUE_URL'), [
                'act' => 'change_channel_order',
                'order_id' => $channel_order->order_id,
                'push_order_sn' => $channel_order->push_order_sn,
                'channel_id' => $channel_order->channel_id,
                'channel_order_status' => $order_status,
            ]);
        }
        return success([], '操作成功');
    }
    public function checkChannelOrder(Request $request, ChannelOrder $model)
    {
        $id_arr = $request->post('ids');

        $channel_order_list = $model->whereIn('channel_order_status', [1, 2])
            ->whereIn('id', $id_arr)
            ->get();
        foreach ($channel_order_list as $channel_order) {
            //异步操作
            sock_get(env('QUEUE_URL'), [
                'act' => 'check_channel_order',
                'order_id' => $channel_order->order_id,
                'push_order_sn' => $channel_order->push_order_sn,
            ]);
        }
        return success([], '操作成功');
    }
    /*改变处理方式*/
    public function updateOrderProcessType(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $type = $request->post('type', 1);

        if (!in_array(intval($type), [1, 2])) {
            return error('类型有误');
        }

        $is_auto = 0;
        if ($type == 2) {
            $is_auto = 1;
        }
        $msg = '变更处理方式：' . ($type == 1 ? '手动' : '自动');

        $order_list = $model->whereIn('order_status', [1, 5, 6])
            ->where('pay_status', 1)
            ->whereIn('id', $id_arr)
            ->get();
        $user = auth()->user();

        foreach ($order_list as $order) {
            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]改变订单处理方式" . ($type == 1 ? '手动' : '自动'),
            ]);
            //更新
            if ($msg) {
                $order->msg = $msg;
            }
            //跳过拦截
            $order->skip_hook = 1;
            $order->order_status = 5;
            $order->is_auto = $is_auto;
            if ($type == 1) {
                // 修改为手动将渠道重置
                $order->channel_id = 0;
            }
            $order->save();
        }

        return success([], '操作成功');
    }
    /*订单重提*/
    public function orderReSubmit(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $password = $request->post('password', '');
        $change_channel = $request->post('change_channel', 0);
        $channel_id = $request->post('channel_id', 0);
        $product_id = $request->post('product_id', 0);

        $user = auth()->user();
        if ($change_channel == 1 && Hash::check($password, $user->password) == false) {
            return error('密码有误');
        }
        if ($change_channel == 1 && $channel_id == 0) {
            return error('请选择渠道');
        }

        $msg = substr($request->post('remark', ''), 0, 100);

        $order_list = $model->whereIn('order_status', [5, 6])
            ->whereIn('id', $id_arr)
            ->where('pay_status', 1)
            ->get();
        $user = auth()->user();
        foreach ($order_list as $order) {
            if ($order->is_auto == 0) {
                continue;
            }

            //20220527 黑名单号码跳过
            if ($this->validateMobileIsBlank($order->mobile)) {
                $order->msg = '黑名单号码';

                $order->save();
                continue;
            }


            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]重提订单",
            ]);
            //更新
            if ($msg) {
                $order->msg = $msg;
            }
            $merchant_info = SysUser::find($order->create_by);

            // 验证余额
            if ($order->order_status == 5 && $order->plat_status == 0) {

                // 验证资金
                if ($merchant_info->balance + $merchant_info->credit < $order->price) {
                    // 资金不足跳过
                    logger("资金不足" . $order->order_sn);
                    logger("merchant_info:" . json_encode($merchant_info));
                    continue;
                }
                // 记录商户资金(消费)
                DB::transaction(function () use ($order, $merchant_info, $change_channel, $channel_id) {
                    $change_price = $order->user_price;
                    $af_money = number_format($merchant_info->balance - $change_price, 2, '.', '');
                    // $af_money = number_format($merchant_info->balance - $order->sale_price, 2, '.', '');
                    // storage_log("af_money" . $af_money);
                    $order_id = $order->id;
                    $res = BalanceLog::create([
                        'order_sn' => $order['order_sn'],
                        'money' => $order->price,
                        'bf_balance' => $merchant_info->balance,
                        'af_balance' => $merchant_info->balance - $order->price,
                        'bank' => '',
                        'type' => 3,
                        'remark' => "{$order->mobile},充值[{$order->title}]，消费{$order->price}元",
                        'user_id' => $merchant_info->id,
                    ]);
                    // 修改订单未已扣款
                    DB::table('cz_order')->where('id', $order_id)->update([
                        "plat_status" => 1,
                        "updated_at" => time(),
                        "msg" => "扣款商户余额",
                    ]);
                    // 修改商户余额
                    // storage_log('售价');
                    // storage_log($order_info->sale_price);
                    $is_dec_balance = DB::table('sys_users')
                        ->where('id', $merchant_info->id)
                        ->where('balance', '>=', ($order->price - $merchant_info->credit))
                        ->decrement('balance', $order->price);
                    // Db::table('member_user')->where('id', $merchant_info->id)->dec('balance', floatval($change_price))->update();

                });
            }
            $order->skip_hook = 1;
            $order->order_status = 1;
            $order->save();


            if ($change_channel == 1 && $channel_id > 0) {
                $data = [
                    "change_channel_id" => $channel_id,
                ];
                if ($product_id) {
                    $data['product_id'] = $product_id;
                }
                sock_queue($order->id, 'queue_order', $data);
            } else {
                $data = [];
                if ($product_id) {
                    $data['product_id'] = $product_id;
                }
                sock_queue($order->id, 'queue_order', $data);
            }
        }

        return success([], '操作成功');
    }

    public function delOrderData(Request $request)
    {
        $date_range = $request->post('params', []);
        if (count($date_range) != 2) {
            return error("请选择时间范围。");
        }

        $beginTime = strtotime($date_range['beginTime']);
        $endTime = strtotime($date_range['endTime']);
        $status_type = $request->post('status_type', 0);
        $table = $request->post('table', '');

        if ((($endTime - $beginTime) / (24 * 3600)) > 31) {
            return error("时间范围不宜超过31天。");
        }

        $params = [
            'params' => $date_range,
        ];

        if ($status_type == 4) {
            $params['channel_order_status'] = 4;
            $params['order_status'] = 4;
        }

        if ($table == 'user_order') {
            CzOrder::filter($params)->delete();
        }

        if ($table == 'channel_order') {
            ChannelOrder::filter($params)->delete();
        }
        return success([], '处理成功');
    }

    /*获取订单数量20220506*/
    public function getOrderNums(Request $request)
    {
        $params  = $request->all();
        $oid = intval($params['oid']);
        if (!$oid) {
            return error('请输入截止订单ID');
        }


        $count = CzOrder::filter($params)->count();
        return success([
            'nums' => $count
        ], '获取成功');
    }
    /*批量改充值中20220506*/
    public function mutiChangeStatus2(Request $request)
    {
        $params = $request->post();

        $nums = $request->post('nums', 0);
        $oid = intval($params['oid']);
        if (!$oid) {
            return error('请输入截止订单ID');
        }

        $batch_sn = $request->post('bsn', '');
        $remark = $request->post('rmk', '');

        $count = CzOrder::filter($params)->count();
        if ($count != $nums) {
            return error("数量不匹配清重新核查[{$nums}----{$count}]");
        }
        if (strlen($batch_sn) < 3) {
            return error('批量订单号不能低于3位');
        }


        if (strlen($remark) < 1) {
            return error('请输入备注信息');
        }

        $is_exist = CzOrder::where('batch_order_sn', $batch_sn)->count();
        if ($is_exist > 0) {
            return error("批量订单号已存在[包含订单：{$is_exist}]");
        }

        $params['order_status_in'] = [1, 5, 6];
        CzOrder::filter($params)->update([
            'order_status' => 2,
            'msg' => $remark,
            'batch_order_sn' => $batch_sn
        ]);
        //        return error('123');
        return success([], "更新成功: {$count}单，批量订单号：{$batch_sn}，时间：" . date("Y-m-d H:i:s"));
    }

    /*缓存压单重新提交*/
    public function cacheOrderSubmit(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $password = $request->post('password');
        $change_channel = $request->post('change_channel', 0);
        $channel_id = $request->post('channel_id', 0);

        $user = auth()->user();
        if ($change_channel == 1 && Hash::check($password, $user->password) == false) {
            return error('密码有误');
        }
        if ($change_channel == 1 && $channel_id == 0) {
            return error('请选择渠道');
        }

        $msg = substr($request->post('remark', ''), 0, 100);

        $order_list = $model->where('order_status', 5)
            ->where('pay_status', 1)
            ->whereIn('id', $id_arr)
            ->get();
        $user = auth()->user();

        foreach ($order_list as $order) {
            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]提交缓存订单处理",
            ]);
            //更新
            if ($msg) {
                $order->msg = $msg;
            }
            //跳过拦截
            $order->skip_hook = 1;
            $order->order_status = 1;
            $order->save();

            if ($change_channel == 1 && $channel_id > 0) {
                sock_queue($order->id, 'queue_order', [
                    'change_channel_id' => $channel_id
                ]);
            } else {
                sock_queue($order->id, 'queue_order');
            }
        }

        return success([], '操作成功');
    }
    /*拦截订单重新提交*/
    public function stopFailOrderSubmit(Request $request, CzOrder $model)
    {
        $id_arr = $request->post('ids');
        $msg = substr($request->post('remark', ''), 0, 100);

        $password = $request->post('password');
        $change_channel = $request->post('change_channel', 0);
        $channel_id = $request->post('channel_id', 0);

        $user = auth()->user();
        if ($change_channel == 1 && Hash::check($password, $user->password) == false) {
            return error('密码有误');
        }
        if ($change_channel == 1 && $channel_id == 0) {
            return error('请选择渠道');
        }


        $order_list = $model->where('order_status', 6)
            ->where('pay_status', 1)
            ->whereIn('id', $id_arr)
            ->get();
        $user = auth()->user();
        foreach ($order_list as $order) {
            CzOrderLog::create([
                'order_id' => $order->id,
                'order_sn' => $order->order_sn,
                'content' => "[{$user->username}]提交失败拦截订单处理",
            ]);
            //更新
            if ($msg) {
                $order->msg = $msg;
            }
            $order->order_status = 1;
            $order->save();

            if ($change_channel == 1 && $channel_id > 0) {
                sock_queue($order->id, 'queue_order', [
                    'change_channel_id' => $channel_id
                ]);
            } else {
                sock_queue($order->id, 'queue_order');
            }
        }
        return success([], '操作成功');
    }
    public function exportCensus(Request $request)
    {
        $params = $request->all();
        if ((!$params['updated_at']['beginTime'] || !$params['updated_at']['endTime']) && (!$params['params']['beginTime'] || !$params['params']['endTime'])) {
            return error('请选择时间范围');
        }
        if (!isset($params['user_id'])) {
            return error('请选择商户');
        }
        $params['pay_status'] = 1;

        $success_total_nums = CzOrder::filter($params)->where('create_by', $params['user_id'])->where('order_status', 3)->count();
        // $success_sum_money = CzOrder::filter($params)->where('create_by', $params['user_id'])->where('order_status', 3)->sum('cost');
        $success_sum_sale_price = CzOrder::filter($params)->where('create_by', $params['user_id'])->where('order_status', 3)->sum('price'); //总售价
        // 退款
        $start = date("Y-m-d", strtotime($params['params']['beginTime'])) . "-01-01 00:00:00";
        $refund_money = CzOrder::where('create_by', $params['user_id'])->where('order_status', 4)
            ->whereBetween('created_at', [strtotime($start), strtotime($params['params']['beginTime'])])
            ->whereBetween('updated_at', [$params['params']['beginTime'], $params['params']['endTime']])
            ->sum('price'); //总售价

        // 累计加款
        if (isset($params['user_id'])) {
            $params['user_id'] = $params['user_id'];
        }
        $all_add_money = BalanceLog::filter($params)->where('type', 1)->sum('money');
        $merchant = SysUser::find($params['user_id']);
        // 期初余额
        $start_money = 0;
        $end_money = 0;

        if (isset($params['user_id'])) {

            if (isset($params['params']['beginTime'])) {
                $start_info = BalanceLog::filter($params)->first();
                if ($start_info) {
                    $start_money = $start_info->bf_balance;
                }

                $end_info = BalanceLog::filter($params)->orderBy('created_at', 'desc')->first();

                if ($end_info) {
                    // af_money
                    $end_money = $end_info->af_balance;
                }

                if (!$end_info || !$start_info) {
                    $start_money = $merchant->balance;
                    $end_money = $merchant->balance;
                }
            }
        }
        $data = [
            "end_money" => $end_money,
            "start_money" => $start_money,
            "refund_money" => $refund_money,
            "start_time" => "",
            "end_time" => "",
            "success_total_nums" => $success_total_nums,
            // "success_sum_money" => $success_sum_money,
            "success_sum_sale_price" => $success_sum_sale_price,

            "all_add_money" => $all_add_money,

        ];


        $data['start_time'] = $params['params']["beginTime"];
        $data['end_time'] = $params['params']["endTime"];
        $data['merchant_name'] = $merchant->username;
        // dd($data);
        $this->excell("快享订单统计.xlsx", $data);
        return;
    }
    public function excell($filename, $data)
    {


        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();


        $sheet->mergeCells("A1:G1");
        $sheet->mergeCells("A2:G2");
        $sheet->mergeCells("A3:G3");
        $sheet->mergeCells("A6:G6");

        $sheet->getStyle('A1:G11')->applyFromArray([
            "font" => [
                "size" => 13
            ],
            "borders" => [
                "allBorders" => [
                    "borderStyle" => Border::BORDER_THIN
                ]
            ]
        ]);

        $sheet->getStyle('A1:G10')->applyFromArray([
            'alignment' => [
                'vertical' => Alignment::VERTICAL_CENTER
            ],
        ]);
        $sheet->getStyle('A1')->applyFromArray([
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_CENTER,
                'vertical' => Alignment::VERTICAL_CENTER
            ],
            "font" => [
                "bold" => true
            ]
        ])->getFont()->setName('黑体');
        $sheet->getStyle('A2')->applyFromArray([
            'alignment' => [
                'vertical' => Alignment::VERTICAL_CENTER
            ],
        ]);
        $sheet->getStyle('A11')->applyFromArray([
            'alignment' => [
                'vertical' => Alignment::VERTICAL_CENTER
            ],
            "font" => [
                "bold" => true,
            ]
        ])->getFont()->setName('黑体');

        $sheet->getStyle('A3')->applyFromArray([
            'alignment' => [
                'vertical' => Alignment::VERTICAL_CENTER
            ],
        ]);
        $sheet->getStyle('A4:G5')->applyFromArray([
            'alignment' => [
                'horizontal' => Alignment::HORIZONTAL_CENTER,
                'vertical' => Alignment::VERTICAL_CENTER
            ],
            "font" => [
                "bold" => true
            ]
        ])->getFont()->setName('黑体');



        $sheet->getRowDimension(1)->setRowHeight(45);
        for ($i = 2; $i <= 11; $i++) {
            // 设置高度
            $sheet->getRowDimension($i)->setRowHeight(35);
        }
        $col_arr = ["A", "B", "C", "D", "E", "F", "G"];
        for ($j = 0; $j < count($col_arr); $j++) {
            $sheet->getColumnDimension($col_arr[$j])->setWidth(25);
        }

        // 写入数据
        $cell1 = $sheet->getCell('A1');
        $v1 = $cell1->setValue("深圳市快享互联科技");

        $cell1 = $sheet->getCell('A2');
        $v1 = $cell1->setValue("说明：以下统计均是成功的订单！");

        $cell1 = $sheet->getCell('A3');
        $v1 = $cell1->setValue("账单周期：" . $data['start_time'] . "至" . $data['end_time']);



        $sheet->getCell('A4')->setValue("期初余额");
        $sheet->getCell('B4')->setValue("加款金额");
        // $sheet->getCell('C4')->setValue("商户总成本");
        $sheet->getCell('C4')->setValue("商户总售价");
        $sheet->getCell('D4')->setValue("商户总笔数");
        $sheet->getCell('E4')->setValue("期末余额");
        $sheet->getCell('F4')->setValue("退款金额");
        $sheet->getCell('G4')->setValue("备注");

        $sheet->getCell('A5')->setValue($data['start_money']);
        $sheet->getCell('B5')->setValue($data['all_add_money']);
        // $sheet->getCell('C5')->setValue($data['success_sum_money']);
        $sheet->getCell('C5')->setValue($data['success_sum_sale_price']);
        $sheet->getCell('D5')->setValue($data['success_total_nums']);
        $sheet->getCell('E5')->setValue($data['end_money']);
        $sheet->getCell('F5')->setValue($data['refund_money']);
        // $sheet->getCell('G5')->setValue();


        $sheet->getCell('A7')->setValue("甲方：");
        $sheet->getCell('B7')->setValue("深圳市快享互联科技");
        $sheet->getCell('A8')->setValue("单位（签章）：");
        $sheet->getCell('A9')->setValue("经办人：");
        $sheet->getCell('B9')->setValue("");
        $sheet->getCell('A10')->setValue("日期：");
        $sheet->getCell('B10')->setValue(date("Y年m月d日"));


        $sheet->getCell('E7')->setValue("乙方：");
        $sheet->getCell('F7')->setValue($data['merchant_name']);
        $sheet->getCell('E8')->setValue("单位（签章）：");
        $sheet->getCell('E9')->setValue("经办人：");
        $sheet->getCell('E10')->setValue("日期： 年 月 日");


        $sheet->mergeCells("A11:F11");
        $sheet->getCell('A11')->setValue("注：请于收到对账但3个工作日内进行核对，如有异议随时沟通，逾期将以我司账单数据作为最终结算数据");


        // $Writer = new Xlsx($spreadsheet);

        header("Content-Type:application/vnd.ms-excel");
        // header("Content-Disposition:attachment;filename=" . "快享订单统计999.xlsx");
        header('Cache-Control:max-age=0');
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: GET,POST,OPTIONS,DELETE,PUT");

        $Writer = IOFactory::createWriter($spreadsheet, "Xlsx");
        $Writer->save("php://output");
        // return;
    }
}
